home *** CD-ROM | disk | FTP | other *** search
- /*
- File: NonDatabaseShape.c
-
- Contains: QuickDraw GX to PostScript conversion code.
- File contains code for the handling of shapes
- who's glyphs were not in the initial font database,
- such as those added by imaging time printing extensions
-
-
- Version: Technology: Quickdraw GX 1.1.x
-
- Copyright: © 1991-1997 by Apple Computer, Inc., all rights reserved.
- */
-
- #include "GXToPSBuildConfig.h"
- #include <GXExceptions.h>
- #include "GXPrintingUniverse.h"
- #include "FontHandler.h"
- #include "FontHandlerPrivate.h"
- #include "FontHandlerVariations.h"
- #include "FontDatabase.h"
-
- #include <GXGraphics.h>
- #include <MacMemory.h>
-
- #ifdef resumeLabel
- #undef resumeLabel
- #endif
- #define resumeLabel(exception)
-
- /*******************************************************
-
- FHBuildShapeDbaseTags:
-
- Routine to build font database tags on a shape.
-
- Routine builds font database tags on a shape by
- flattening it. The actual flattened information
- is ignored. We only want to get the tags built.
-
- Routine returns a picture that has the database tags
- on it. This is because flattening does not generate
- the font database on normal shapes, just pictures.
-
- The picture is newly created and must therefore be disposed
- of by the client of this call.
-
- *********************************************************/
- static long FHSpoolProc(gxSpoolCommand command, struct gxSpoolBlock *block)
- {
- #pragma unused (command, block)
-
- /** do nothing **/
-
- return(0);
- }
-
- gxShape FHBuildShapeDbaseTags(gxShape theShape);
- gxShape FHBuildShapeDbaseTags(gxShape theShape)
- {
- gxSpoolBlock theSpool;
- char dummyBuffer[50]; // a place for gx graphics to stick data.
- gxShape thePict;
-
- thePict = GXNewShape(gxPictureType);
- GXSetPictureParts(thePict, 0, 0, 1, &theShape, nil, nil, nil);
-
- theSpool.spoolProcedure = NewgxSpoolProc(FHSpoolProc);
- theSpool.buffer = dummyBuffer;
- theSpool.bufferSize = 50;
-
- GXFlattenShape(thePict, gxFontListFlatten + gxFontGlyphsFlatten + gxFontVariationsFlatten, &theSpool);
-
- DisposeRoutineDescriptor(theSpool.spoolProcedure);
-
- return(thePict);
-
- }//FHBuildShapeDbaseTags
-
-
- //<FF>
- /******************************************
-
- Function: FHRemoveBits
-
- Function clears bits in the destination
- that are set in the source.
-
- *******************************************/
- void FHRemoveBits(unsigned long *source, unsigned long *dest, long numLongs);
- void FHRemoveBits(unsigned long *source, unsigned long *dest, long numLongs)
- {
- register short i;
-
- check( numLongs <= 0x0000FFFF); /* Just for robustness in debugging build */
-
- for (i = numLongs - 1; i >= 0; --i)
- *dest++ &= ~(*source++);
-
- }//FHRemoveBits
-
-
-
-
-
- /****************************************
-
- Function: FHFindMatchingDBBits
-
- Function finds the bit array in the font
- database that matches the font and the variations
- specified. This can also be used to determine the
- dbIndex of a particular variation in the database.
-
- fontDbase: A font database object (Assumed locked).
- theFont: The font to search on.
- axisCount: number of variation axes.
- variations: The variations to search for.
- theBits: will return the pointer to the bit array in here, nil if no match. (pass nil if you don't care)
- dbIndex: Will return the index of the bit array in the database (pass nil if you don't care)
-
- *****************************************/
- OSErr FHFindMatchingDBBits(TFontDbase fontDbase, gxFont theFont, long axisCount, gxFontVariation *variations,
- unsigned long* *theBits, long *dbIndex);
- OSErr FHFindMatchingDBBits(TFontDbase fontDbase, gxFont theFont, long axisCount, gxFontVariation *variations,
- unsigned long* *theBits, long *dbIndex)
- {
- OSErr status;
- long nVariations; // number of variations in the database already.
- long idx; // loop counter for variations.
- gxFontVariation *dbVariations; // variations from the database.
- unsigned long *dbBits; // bits from the database.
-
- /* Find out the number of variations in the database for this font */
-
- status = FontDbaseGetFontInfo(fontDbase, theFont, nil, nil, &nVariations, nil);
- nrequire(status, failed_Info);
-
- /** Now loop through to see if we find a match **/
-
- if (theBits != nil)
- *theBits = nil; // no match yet.
-
- if (dbIndex != nil)
- *dbIndex = eNotPresent; // no match yet.
-
- for (idx = 1; idx <= nVariations; ++idx) {
-
- /** compare variations from database against the ones passed in **/
-
- status = FontDbaseGetGlyphBits(fontDbase, theFont, idx, &dbBits, &dbVariations);
- nrequire(status, failed_Bits);
-
- if ( FHEqualVariations(axisCount, variations, dbVariations) ) {
-
- if (theBits != nil)
- *theBits = dbBits;
-
- if (dbIndex != nil)
- *dbIndex = idx;
-
- break;
-
- }//end if
-
- }//end for
-
- failed_Bits:
- failed_Info:
-
- return(status);
-
- }//FHFindMatchingDBBits
-
- //<FF>
- /******************************************
-
- Function: FHRemoveExistingGlyphBits:
-
- Function clears any bits in a flatFontListItem that
- are already accounted for in the font database.
-
- hFHRec: font hander context handle.
- fontUsage: the flat font list item to use for updating.
-
- *********************************************/
- OSErr FHRemoveExistingGlyphBits(TFontHandlerHdl hFHRec, gxFlatFontListItem *fontUsage);
- OSErr FHRemoveExistingGlyphBits(TFontHandlerHdl hFHRec, gxFlatFontListItem *fontUsage)
- {
- OSErr status;
- long i;
- TFontDbase fontDbase;
- TFontHandlerRec *pFHRec;
- unsigned long *existingBits; // bits from the database.
- unsigned long *newBits; // bits from the fontUsage tag.
- long axisCount; // axis count from the database.
- long variationCount; // variation count from the database.
- long nGlyphs; // number of glyphs in the font.
- gxFontVariation *newVariations; // The new variations.
- unsigned char *p;
- long nameLen, bitsLen;
- Boolean lockedIt = false; // Have we locked the font database?
-
- HLock((Handle)hFHRec);
- pFHRec = *hFHRec;
- fontDbase = pFHRec->docDbase;
- HUnlock((Handle)hFHRec);
-
- /** Get database info for the font **/
-
- status = FontDbaseGetFontInfo(fontDbase, fontUsage->fontID, nil, nil, nil, nil);
- if (status != collectionItemNotFoundErr) {
-
- nrequire(status, failed_GetFontInfo);
-
- status = FontDbaseLock(fontDbase);
- nrequire(status, failed_Lock);
- lockedIt = true;
-
- nGlyphs = fontUsage->glyphCount;
- axisCount = fontUsage->axisCount;
- nameLen = 4 * ( (fontUsage->length + 3) / 4);
- bitsLen = 4 * ( (nGlyphs + 31) / 32);
-
- /*** First, clear the main bit array of any glyphs already in the database ***/
-
- status = FontDbaseGetGlyphBits(fontDbase, fontUsage->fontID, eMainBits, &existingBits, nil);
- nrequire(status, failed_GetBits);
-
- p = (unsigned char*)fontUsage + nameLen;
- newBits = (unsigned long*)p;
-
- FHRemoveBits(existingBits, newBits, bitsLen / 4);
-
- /*** No do the same for all of the variations bit arrays already in the database ***/
-
- p += bitsLen;
-
- for (i = 1; i < fontUsage->variationCount; ++i) {
-
- newBits = (unsigned long*)p;
- newVariations = (gxFontVariation*)(p + bitsLen);
-
- status = FHFindMatchingDBBits(fontDbase, fontUsage->fontID, axisCount, newVariations, &existingBits, nil);
- nrequire(status, failed_FindMatch);
-
- /*****
- If the database contained a matching variation,
- clear the bits in the fontUsage that were already in the database.
- nil return for pointer to bits means couldn't find match.
- *****/
-
- if (existingBits != nil)
- FHRemoveBits(existingBits, newBits, bitsLen / 4);
-
- p += bitsLen + axisCount * sizeof(gxFontVariation);
-
- }//end for
-
- } else {
-
- /* collectionItemNotFoundErr means the font is not in the database, this is okay */
-
- status = noErr;
-
- }//end if
-
- failed_FindMatch:
- failed_GetBits:
-
- if (lockedIt) {
-
- OSErr saveStatus = FontDbaseUnlock(fontDbase);
- if (status != noErr)
- status = saveStatus;
-
- ncheck(status);
-
- }//end if
-
- failed_Lock:
- failed_GetFontInfo:
-
- return(status);
-
- }//FHRemoveExistingGlyphBits
-
-
- /*****************************************
-
- Function: FHNonDBBuildPrinterFonts
-
- Function builds the printer fonts records for
- the non-database shape case. This code is quite
- similar to the FHBuildPrinterFontList code in
- FontHandler.c. Not similar enough to share code,
- however. Here, dbIndex values must be obtained
- by calling the FindMatchingDBBits routine rather
- than simply traversing the font database. Bit arrays
- come from the flatfontlistitem rather than the database
- as well.
-
- ********************************************/
- OSErr FHNonDBBuildPrinterFonts(TFontHandlerHdl hFHRec, gxFlatFontListItem *fontUsage);
- OSErr FHNonDBBuildPrinterFonts(TFontHandlerHdl hFHRec, gxFlatFontListItem *fontUsage)
- {
- OSErr status;
- long varCounter; // count through the variations in the fontUsage.
- long dbIndex; // dbIndex of the variation.
- long bitsSize; // size of bit array (in bytes).
- long variationSize; // size of variations (in bytes)
- gxFontVariation *variations;
- unsigned long *glyphBits; // glyph usage bit array.
- fhFont snapshotID; // snapshot id.
- unsigned char *p; // Pointer into structure.
- TFHStreamRequirements requirements; // Stream requirements.
-
- /* Test to see if we need snapshots for this font or if the font can't be streamed at all */
-
- status = FHGetStreamRequirements(fontUsage->fontID, (*hFHRec)->psDevice, (*hFHRec)->legalStreamTypes,
- (*hFHRec)->productDescription, &requirements);
- nrequire(status, failed_Test);
-
- /* Point p at first bit array */
-
- p = (unsigned char*)fontUsage;
- p += sizeof(gxFlatFontListItem) + 4 * ((fontUsage->length + 3) / 4); // add size of struct + long alligned name.
- bitsSize = 4 *((fontUsage->glyphCount + 31) / 32);
- variationSize = fontUsage->axisCount * sizeof(gxFontVariation);
-
- /* Build the appropriate printer fonts */
-
- if (requirements == fhNeedsSnapShots) {
-
- /**** Add a snapshot for each variation used ****/
-
- p += bitsSize; // skip past main bits.
-
- for (varCounter = 0; varCounter < fontUsage->variationCount; ++varCounter) {
-
- glyphBits = (unsigned long*)p;
- variations = (gxFontVariation*)(p + bitsSize);
-
- /** Get the dbIndex for this variation **/
- status = FHFindMatchingDBBits((*hFHRec)->docDbase, fontUsage->fontID, fontUsage->axisCount,
- variations, nil, &dbIndex);
- nrequire(status, failed_FindMatch);
-
- ncheck(dbIndex == eNotPresent); // should never happen.
-
- status = FHAddFontSnapShot(hFHRec, fontUsage->fontID, dbIndex, &snapshotID);
- nrequire(status, failed_snapshot);
-
- status = FHAddPrinterFonts(hFHRec, snapshotID, glyphBits, fontUsage->glyphCount, fdbNoFontFlags);
- nrequire(status, failed_AddPrinterFont);
-
- /* Point to the next pair */
-
- p += bitsSize + variationSize;
-
- }//end for
-
- } else {
-
- /**** Just add one snapshot for the main bit array ****/
-
- status = FHAddFontSnapShot(hFHRec, fontUsage->fontID, eMainBits, &snapshotID);
- nrequire(status, failed_snapshot);
-
- status = FHAddPrinterFonts(hFHRec, snapshotID, (unsigned long*)p, fontUsage->glyphCount, fdbNoFontFlags);
- nrequire(status, failed_AddPrinterFont);
-
- }//end if
-
- failed_FindMatch:
- failed_snapshot:
- failed_AddPrinterFont:
- failed_Test:
-
- return(status);
-
- }//FHNonDBBuildPrinterFonts
-
-
- //<FF>
- /******************************************
-
- FHAddNonDatabaseShape:
-
- Routine generates printer-font records for
- non-database resident glyphs from a shape.
-
- 1. Flatten the shape to get database tags.
-
- 2. For each database tag:
-
- 2a. Clear any glyph bits in the new tags that are already
- in the font database
-
- 2b. update the database with new ones.
-
- 2c. Build printer-fonts for the new entries.
-
- *******************************************/
- OSErr FHAddNonDatabaseShape(TFontHandlerHdl hFHRec, gxShape theShape)
- {
- OSErr status;
- gxTag fontUsageTag;
- gxFlatFontListItem *fontUsage;
- long nFonts;
- long i;
- TFontDbase docDbase;
- gxShape thePict;
-
- /**** First build font database tags ****/
-
- thePict = FHBuildShapeDbaseTags(theShape);
- nrequire(status = GXGetGraphicsError(nil), failed_FHBuildShapeDbaseTags);
-
- /** Get the font information that flattening added to the shape **/
-
- nFonts = GXGetShapeTags(thePict, gxFlatFontListItemTag, 1, gxSelectToEnd, nil);
-
- for (i = 1; (i <= nFonts) && (status == noErr); ++i) {
-
- /* Get a pointer to the flat font list item from the tag */
-
- GXGetShapeTags(thePict, gxFlatFontListItemTag, i, 1, &fontUsageTag);
- fontUsage = (gxFlatFontListItem*)GXGetTagStructure(fontUsageTag, nil);
- nrequire(status = GXGetGraphicsError(nil), failed_LockTag);
-
- /* Clear bits in the item that are already in the database */
-
- status = FHRemoveExistingGlyphBits(hFHRec, fontUsage);
- nrequire(status, failed_UpdateDbase);
-
- /* Update the database so it contains entries for any new font/variation combinations */
-
- docDbase = (*hFHRec)->docDbase;
- status = FontDbaseAddItem(docDbase, fontUsage, false);
- nrequire(status, failed_AddItem);
-
- /* Build the printer fonts for this tag */
-
- status = FHNonDBBuildPrinterFonts(hFHRec, fontUsage);
- nrequire(status, failed_BuildPrinterFonts);
-
- failed_BuildPrinterFonts:
- failed_AddItem:
- failed_UpdateDbase:
-
- /* Unlock the tag */
-
- GXUnlockTag(fontUsageTag);
-
- }//end for
-
- failed_LockTag:
-
-
-
- /*** Now Dispose of the database picture, we don't need it any more ***/
-
- GXDisposeShape(thePict);
-
- {
- OSErr saveStatus = GXGetGraphicsError(nil);
- if (status == noErr)
- status = saveStatus;
-
- ncheck(status);
- }
-
- failed_FHBuildShapeDbaseTags:
-
- return(status);
-
- }//FHAddNonDatabaseShape
-
-